<script setup lang="ts" name="GoodsSku">
import { GoodsInfo, Spec, SpecValue } from '@/types/goods'
import bwPowerSet from '@/utils/bwPowerset'
const emit = defineEmits<{
  (e: 'changeSku', skuId: string): void
}>()

//sku 组件的基本使用
// 1.(必须)传入，商品信息对象 =》 拥有了启用禁用，选择功能
// 2.(可选)传入 skuid      =>默认回显，默认让一些规格选中
// 3.当 全部规格  选完的时候，就是确定了一个sku 需要子传父，将skuid 传给父即可

const props = defineProps<{
  goods: GoodsInfo
  skuId?: string
}>()

//+号 声明为常量了
const SPLIT_STR = '+'

//bwPowerSet([属性1， 属性2， 属性3]) => 帮你求子集
// const arr = bwPowerSet(['红色', '180cm', '国产'])
// console.log(arr)

// 修改按钮的选中状态
const changeSelected = (spec: Spec, specValue: SpecValue) => {
  if (specValue.disabled) return
  // console.log('改变选中状态')
  // specValue.selected = true
  // 1.如果选中了，二次点击，取消选中
  // 2.如果没选中，让他选中，排他
  if (specValue.selected) {
    specValue.selected = false
  } else {
    // 排他，先干点所有人，在复活自己
    spec.values.forEach(v => (v.selected = false))
    specValue.selected = true
  }

  // 一旦按钮被重新选择了，按钮状态也会随之需要更新
  updateDisabledStatus()

  //①判断，是否所有可选规格，都选择 ，用过滤是因为有空值
  const selectArr = getSelectedSepc().filter(item => item)
  //判断数量是否相等
  if (selectArr.length === props.goods.specs.length) {
    // ②说明全部选中，将得到的数组，转成字符串，去pathmap中对应找id
    const key = selectArr.join(SPLIT_STR) //'蓝色+10cm+中国'
    const result = pathMap[key]
    const skuId = result[0] //这个skuid，是result中唯一值
    emit('changeSku', skuId)
  }

  // 完善组合禁用效果 不调用此条代码
  // const arr = getSelectedSepc()
  // console.log(arr)
}

// 一进入页面，控制启用禁用状态 => 需要路径字典
// 基于数据skus，得到路径字典
const getPathMap = () => {
  const pathMap: any = {}
  // console.log(props.goods.skus)
  // 1.过滤所有的skus,得到有效的skus(库存》0)
  const skus = props.goods.skus.filter(item => item.inventory > 0)
  // console.log(skus)

  // 2.遍历有效的sku,获取sku的子集，进行处理
  skus.forEach(sku => {
    // console.log(sku.specs)
    // 3.整理数据，整理得到【属性1，属性2，属性3】
    const arr = sku.specs.map(item => item.valueName)
    // console.log(arr)
    // 4.基于整理的属性列表，求子集
    const PowerSet = bwPowerSet(arr)
    // console.log(PowerSet)
    // 5.遍历子集，将子集的数据 往pathMap中整理
    //① 如果筛选条件，不存在，新开一个属性，存
    //② 如果筛选条件，已存在，在已有属性上，累加
    // pathMap: { 键：{ skuId1, skuId2}}
    // console.log(PowerSet)
    PowerSet.forEach(sub => {
      // 将数组的信息，拼合成一个字符串，将来作为键（sku.id作为值）
      const key = sub.join(SPLIT_STR) // split 切割
      // 判断键在对象中是否存在
      if (key in pathMap) {
        // 已存在，在已有属性值累加
        pathMap[key].push(sku.id)
      } else {
        // 不存在，直接新开一个属性，属性值，是一个有一项内容的数组
        pathMap[key] = [sku.id]
      }
      console.log(key)
      console.log(pathMap)
    })
  })
  return pathMap
}

// 更新启用禁用状态
const updateDisabledStatus = () => {
  const selectArr = getSelectedSepc() // ['', '', '日本']
  // 根据路径字典 =》更新所有的按钮specValue的状态
  props.goods.specs.forEach((spec, index) => {
    spec.values.forEach(specValue => {
      //让当前这个按钮，specVale.name（黑色） 和 selectArr 进行组合
      // 叠加['黑色'， '', '日本']
      // 注意：这边尝试组合，判断是否禁用时，需要拷贝一份原数组
      const tempArr = [...selectArr]
      tempArr[index] = specValue.name //['黑色'， '', '日本']
      // console.log(specValue.name)
      //得到组合后转换字符串的key ‘黑色+日本’
      const key = tempArr.filter(item => item).join(SPLIT_STR)
      if (key in pathMap) {
        // 存在，有库存，不禁用
        specValue.disabled = false
      } else {
        // 不存在，没有库存了，禁用掉
        specValue.disabled = true
      }
    })
  })
}

//获取当前选中的状态
const getSelectedSepc = () => {
  //根据现有的所有按钮，进行遍历，将选中的值，按照下标存入数组
  const arr = ['', '', '']
  props.goods.specs.forEach((spec, index) => {
    // spec.values.forEach(specValua => {
    //   console.log(specValua.selected)
    // })
    const temObj = spec.values.find(specValue => specValue.selected)
    arr[index] = temObj ? temObj.name : ''
  })
  return arr
}
//默认根据父传子，传递的skuid,进行回显，设置选中状态
const initSelectedSpec = () => {
  if (!props.skuId) return
  const sku = props.goods.skus.find(item => item.id === props.skuId)
  if (!sku) return
  // 基于sku.specs，让按钮设置成选中状态
  props.goods.specs.forEach((spec, index) => {
    // find ,三个按钮中，其实，只有一个被选中
    const text = sku.specs[index].valueName
    const specValua = spec.values.find(item => item.name === text)
    specValua!.selected = true
    // console.log(sku.specs[index].valueName)
  })
}
// 1.获取路径字典
const pathMap = getPathMap()
// 2.先按照skuid 进行初始化，将选中状态设置好
initSelectedSpec()
// 3. 根据目前已经选中的项=>更新禁用状态
updateDisabledStatus()
console.log(pathMap)
</script>
<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.name">
      <dt>{{ item.name }}</dt>
      <dd>
        <!-- 既要用 v-for  又要用 v-if   +template -->
        <template v-for="sub in item.values" :key="sub.name">
          <img
            v-if="sub.picture"
            :class="{ selected: sub.selected, disabled: sub.disabled }"
            :src="sub.picture"
            alt=""
            @click="changeSelected(item, sub)"
          />
          <span
            v-else
            @click="changeSelected(item, sub)"
            :class="{ selected: sub.selected, disabled: sub.disabled }"
          >
            {{ sub.name }}
          </span>
        </template>
      </dd>
    </dl>
  </div>
</template>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
